using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace OracleInternal.I18N
{
	internal class TLBConvSerializer
	{
		private const string BOOT_FILE_NAME = "lx0boot.glb";

		internal static void Serialize(object obj, Stream stream)
		{
			if (obj is TLBConv)
			{
				if (obj is TLBConv1Byte)
				{
					Serialize((TLBConv1Byte)obj, stream);
				}
				else if (obj is TLBConv12Byte)
				{
					Serialize((TLBConv12Byte)obj, stream);
				}
				else
				{
					Serialize((TLBConvLC)obj, stream);
				}
			}
			else
			{
				Serialize((TLBConvBoot)obj, stream);
			}
		}

		internal static object Deserialize(Stream stream, string fileName)
		{
			if (fileName.Contains("lx0boot.glb"))
			{
				return DeserializeTLBConvBoot(stream);
			}
			int num = new BinaryReader(stream).ReadInt32();
			switch (num)
			{
			case 0:
				return DeserializeTLBConv1Byte(stream, num);
			case 1:
			case 4:
			case 7:
			case 9:
			case 13:
				return DeserializeTLBConv12Byte(stream, num);
			case 2:
			case 5:
				return DeserializeTLBConvLC(stream, num);
			default:
				return null;
			}
		}

		private static void Serialize(TLBConvLC obj, Stream stream)
		{
			BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);
			Serialize(obj.m_groupId, writer);
			Serialize(obj.extraUnicodeToOracleMapping, writer);
			Serialize(obj.m_1ByteOraCharReplacement, writer);
			Serialize(obj.m_2ByteOraCharReplacement, writer);
			Serialize(obj.m_ucsCharLeadingCode, writer);
			Serialize(obj.m_ucsCharLevel1, writer);
			Serialize(obj.m_ucsCharLevel2, writer);
			Serialize(obj.m_ucsCharReplacement, writer);
			Serialize(obj.OracleId, writer);
			Serialize(obj.m_oraCharLevel1, writer);
			Serialize(obj.m_oraCharLevel2, writer);
			Serialize(obj.m_oraCharSurrogateLevel, writer);
		}

		private static TLBConvLC DeserializeTLBConvLC(Stream stream, int typeID)
		{
			TLBConvLC tLBConvLC = ((typeID != 2) ? ((TLBConvLC)new TLBConvZHTEUC()) : ((TLBConvLC)new TLBConvJAEUC()));
			BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);
			tLBConvLC.m_groupId = typeID;
			tLBConvLC.extraUnicodeToOracleMapping = DeserializeInt2DArray(reader);
			tLBConvLC.m_1ByteOraCharReplacement = DeserializeChar(reader);
			tLBConvLC.m_2ByteOraCharReplacement = DeserializeChar(reader);
			tLBConvLC.m_ucsCharLeadingCode = DeserializeChar2DArray(reader);
			tLBConvLC.m_ucsCharLevel1 = DeserializeCharArray(reader);
			tLBConvLC.m_ucsCharLevel2 = DeserializeIntArray(reader);
			tLBConvLC.m_ucsCharReplacement = DeserializeInt(reader);
			tLBConvLC.OracleId = DeserializeInt(reader);
			tLBConvLC.m_oraCharLevel1 = DeserializeCharArray(reader);
			tLBConvLC.m_oraCharLevel2 = DeserializeIntArray(reader);
			tLBConvLC.m_oraCharSurrogateLevel = DeserializeCharArray(reader);
			return tLBConvLC;
		}

		private static void Serialize(TLBConv1Byte obj, Stream stream)
		{
			BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);
			Serialize(obj.m_groupId, writer);
			Serialize(obj.extraUnicodeToOracleMapping, writer);
			Serialize(obj.m_oraCharLevel2Size, writer);
			Serialize(obj.m_oraCharReplacement, writer);
			Serialize(obj.m_ucsChar, writer);
			Serialize(obj.m_ucsReplacement, writer);
			Serialize(obj.noSurrogate, writer);
			Serialize(obj.OracleId, writer);
			Serialize(obj.strictASCII, writer);
			Serialize(obj.m_oraCharLevel1, writer);
			Serialize(obj.m_oraCharLevel2, writer);
			Serialize(obj.m_oraCharSurrogateLevel, writer);
		}

		private static TLBConv1Byte DeserializeTLBConv1Byte(Stream stream, int typeID)
		{
			BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);
			return new TLBConv1Byte
			{
				m_groupId = typeID,
				extraUnicodeToOracleMapping = DeserializeInt2DArray(reader),
				m_oraCharLevel2Size = DeserializeInt(reader),
				m_oraCharReplacement = DeserializeByte(reader),
				m_ucsChar = DeserializeIntArray(reader),
				m_ucsReplacement = DeserializeInt(reader),
				noSurrogate = DeserializeBool(reader),
				OracleId = DeserializeInt(reader),
				strictASCII = DeserializeBool(reader),
				m_oraCharLevel1 = DeserializeCharArray(reader),
				m_oraCharLevel2 = DeserializeCharArray(reader),
				m_oraCharSurrogateLevel = DeserializeCharArray(reader)
			};
		}

		private static void Serialize(TLBConv12Byte obj, Stream stream)
		{
			BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);
			Serialize(obj.m_groupId, writer);
			Serialize(obj.extraUnicodeToOracleMapping, writer);
			Serialize(obj.m_1ByteOraCharReplacement, writer);
			Serialize(obj.m_2ByteOraCharReplacement, writer);
			Serialize(obj.m_ucsCharLevel1, writer);
			Serialize(obj.m_ucsCharLevel2, writer);
			Serialize(obj.m_ucsCharReplacement, writer);
			Serialize(obj.OracleId, writer);
			Serialize(obj.m_oraCharLevel1, writer);
			Serialize(obj.m_oraCharLevel2, writer);
			Serialize(obj.m_oraCharSurrogateLevel, writer);
		}

		private static TLBConv12Byte DeserializeTLBConv12Byte(Stream stream, int typeID)
		{
			TLBConv12Byte tLBConv12Byte = typeID switch
			{
				1 => new TLBConv12Byte(), 
				9 => new TLBConvGB18030(), 
				13 => new TLBConvGBK(), 
				7 => new TLBConvShift(), 
				_ => new TLBConvSJIS(), 
			};
			BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);
			tLBConv12Byte.m_groupId = typeID;
			tLBConv12Byte.extraUnicodeToOracleMapping = DeserializeInt2DArray(reader);
			tLBConv12Byte.m_1ByteOraCharReplacement = DeserializeChar(reader);
			tLBConv12Byte.m_2ByteOraCharReplacement = DeserializeCharArray(reader);
			tLBConv12Byte.m_ucsCharLevel1 = DeserializeCharArray(reader);
			tLBConv12Byte.m_ucsCharLevel2 = DeserializeIntArray(reader);
			tLBConv12Byte.m_ucsCharReplacement = DeserializeInt(reader);
			tLBConv12Byte.OracleId = DeserializeInt(reader);
			tLBConv12Byte.m_oraCharLevel1 = DeserializeIntArray(reader);
			tLBConv12Byte.m_oraCharLevel2 = DeserializeCharArray(reader);
			tLBConv12Byte.m_oraCharSurrogateLevel = DeserializeIntArray(reader);
			return tLBConv12Byte;
		}

		private static void Serialize(TLBConvBoot obj, Stream stream)
		{
			BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);
			Serialize(obj.availableCharSet.ToList(), writer);
			Serialize(obj.charSetIdMap, writer);
			Serialize(obj.idtoCharSetMap, writer);
			Serialize(obj.idtoCharSetMaxLen, writer);
			Serialize((List<string>)obj.lstCharSetIsAscii, writer);
			Serialize((List<string>)obj.lstCharSetIsEbcdic, writer);
			Serialize((List<string>)obj.lstCharSetIsFixed, writer);
			Serialize((List<string>)obj.lstCharSetIsStorage, writer);
		}

		private static TLBConvBoot DeserializeTLBConvBoot(Stream stream)
		{
			BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);
			return new TLBConvBoot
			{
				availableCharSet = DeserializeList(reader).ToArray(),
				charSetIdMap = DeserializeDictionary(reader),
				idtoCharSetMap = DeserializeDictionary(reader),
				idtoCharSetMaxLen = DeserializeDictionary(reader),
				lstCharSetIsAscii = DeserializeList(reader),
				lstCharSetIsEbcdic = DeserializeList(reader),
				lstCharSetIsFixed = DeserializeList(reader),
				lstCharSetIsStorage = DeserializeList(reader)
			};
		}

		private static void Serialize(Dictionary<string, string> dictionary, BinaryWriter writer)
		{
			writer.Write(dictionary.Count);
			foreach (KeyValuePair<string, string> item in dictionary)
			{
				writer.Write(item.Key);
				writer.Write(item.Value);
			}
			writer.Flush();
		}

		private static Dictionary<string, string> DeserializeDictionary(BinaryReader reader)
		{
			int num = reader.ReadInt32();
			Dictionary<string, string> dictionary = new Dictionary<string, string>(num);
			for (int i = 0; i < num; i++)
			{
				string key = reader.ReadString();
				string value = reader.ReadString();
				dictionary.Add(key, value);
			}
			return dictionary;
		}

		private static void Serialize(List<string> list, BinaryWriter writer)
		{
			writer.Write(list.Count);
			foreach (string item in list)
			{
				writer.Write(item);
			}
			writer.Flush();
		}

		private static List<string> DeserializeList(BinaryReader reader)
		{
			int num = reader.ReadInt32();
			List<string> list = new List<string>(num);
			for (int i = 0; i < num; i++)
			{
				string item = reader.ReadString();
				list.Add(item);
			}
			return list;
		}

		private static void Serialize(char c, BinaryWriter writer)
		{
			writer.Write(c);
			writer.Flush();
		}

		private static char DeserializeChar(BinaryReader reader)
		{
			return reader.ReadChar();
		}

		private static void Serialize(char[] array, BinaryWriter writer)
		{
			if (array == null)
			{
				writer.Write(0);
				writer.Flush();
				return;
			}
			int num = array.Length;
			writer.Write(num);
			if (num > 0)
			{
				writer.Write(array);
			}
			writer.Flush();
		}

		private static char[] DeserializeCharArray(BinaryReader reader)
		{
			int num = reader.ReadInt32();
			char[] result = new char[num];
			if (num > 0)
			{
				result = reader.ReadChars(num);
			}
			return result;
		}

		private static void Serialize(char[][] array, BinaryWriter writer)
		{
			int length = array.GetLength(0);
			writer.Write(length);
			if (length > 0)
			{
				for (int i = 0; i < length; i++)
				{
					if (i == 0)
					{
						writer.Write(array[i].Length);
					}
					writer.Write(array[i]);
				}
			}
			writer.Flush();
		}

		private static char[][] DeserializeChar2DArray(BinaryReader reader)
		{
			int count = 0;
			int num = reader.ReadInt32();
			char[][] array = new char[num][];
			if (num > 0)
			{
				for (int i = 0; i < num; i++)
				{
					if (i == 0)
					{
						count = reader.ReadInt32();
					}
					array[i] = reader.ReadChars(count);
				}
			}
			return array;
		}

		private static void Serialize(int c, BinaryWriter writer)
		{
			writer.Write(c);
			writer.Flush();
		}

		private static int DeserializeInt(BinaryReader reader)
		{
			return reader.ReadInt32();
		}

		private static void Serialize(int[] array, BinaryWriter writer)
		{
			if (array == null)
			{
				writer.Write(0);
				writer.Flush();
				return;
			}
			int num = array.Length;
			writer.Write(num);
			if (num > 0)
			{
				for (int i = 0; i < num; i++)
				{
					writer.Write(array[i]);
				}
			}
			writer.Flush();
		}

		private static int[] DeserializeIntArray(BinaryReader reader)
		{
			int num = reader.ReadInt32();
			int[] array = new int[num];
			if (num > 0)
			{
				for (int i = 0; i < num; i++)
				{
					array[i] = reader.ReadInt32();
				}
			}
			return array;
		}

		private static void Serialize(int[][] array, BinaryWriter writer)
		{
			int num = 0;
			int length = array.GetLength(0);
			writer.Write(length);
			if (length > 0)
			{
				for (int i = 0; i < length; i++)
				{
					if (i == 0)
					{
						num = array[i].Length;
						writer.Write(num);
					}
					for (int j = 0; j < num; j++)
					{
						writer.Write(array[i][j]);
					}
				}
			}
			writer.Flush();
		}

		private static int[][] DeserializeInt2DArray(BinaryReader reader)
		{
			int num = 0;
			int num2 = reader.ReadInt32();
			int[][] array = new int[num2][];
			if (num2 > 0)
			{
				for (int i = 0; i < num2; i++)
				{
					if (i == 0)
					{
						num = reader.ReadInt32();
					}
					int[] array2 = new int[num];
					for (int j = 0; j < num; j++)
					{
						array2[j] = reader.ReadInt32();
					}
					array[i] = array2;
				}
			}
			return array;
		}

		private static void Serialize(byte b, BinaryWriter writer)
		{
			writer.Write(b);
			writer.Flush();
		}

		private static byte DeserializeByte(BinaryReader reader)
		{
			return reader.ReadByte();
		}

		private static void Serialize(bool b, BinaryWriter writer)
		{
			writer.Write(b);
			writer.Flush();
		}

		private static bool DeserializeBool(BinaryReader reader)
		{
			return reader.ReadBoolean();
		}
	}
}
